package beautiful.butterfly.drds.datasource.connection_contexts.spi;

//import beautiful.butterfly.drds.datasource.author.Author;
//import beautiful.butterfly.drds.datasource.author.Authors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

//import ws.annotation.Describe;

//@Author(name = Authors.LI_YANG)
//@Describe("共享连接")
public final class SharedConnection {
    public static final Logger logger = LoggerFactory.getLogger(SharedConnection.class);

    public final AbstractConnectionContexts abstractConnectionContexts;
    private final Connection connection;

    //
    private boolean readOnly;
    private boolean autoCommit;
    private int transactionIsolation;

    private final boolean defaultReadOnly;
    private final boolean defaultAutoCommit;
    private final int defaultTransactionIsolation;
    //

    private boolean discard = false;
    //
    public final long startTimeMillis;
    public transient long lastActiveTimeMillis;
    //
    private final List<Sql> sqlList = new CopyOnWriteArrayList<Sql>();

    //

    public SharedConnection(AbstractConnectionContexts abstractConnectionContexts, Connection connection) throws SQLException {
        this.abstractConnectionContexts = abstractConnectionContexts;
        this.connection = connection;
        //
        this.readOnly = connection.isReadOnly();
        this.autoCommit = connection.getAutoCommit();
        this.transactionIsolation = connection.getTransactionIsolation();
        //
        this.defaultReadOnly = this.readOnly;
        this.defaultTransactionIsolation = this.transactionIsolation;
        this.defaultAutoCommit = this.autoCommit;
        //

        this.discard = false;
        //
        this.startTimeMillis = System.currentTimeMillis();// 构建的时间
        this.lastActiveTimeMillis = this.startTimeMillis;

    }

    //
    public AbstractConnectionContexts getAbstractConnectionContexts() {
        return abstractConnectionContexts;
    }

    public Connection getConnection() {
        return connection;
    }

    //
    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

    public boolean isReadOnly() {
        return readOnly;
    }

    //
    public void setAutoCommit(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }

    public boolean isAutoCommit() {
        return autoCommit;
    }

    //
    public void setTransactionIsolation(int transactionIsolation) {
        this.transactionIsolation = transactionIsolation;
    }

    public int getTransactionIsolation() {
        return transactionIsolation;
    }

    //

    public long getStartTimeMillis() {
        return startTimeMillis;
    }

    public void setLastActiveTimeMillis(long lastActiveMillis) {
        this.lastActiveTimeMillis = lastActiveMillis;
    }

    public long getLastActiveTimeMillis() {
        return lastActiveTimeMillis;
    }

    //
    public void addSql(Sql sql) {
        this.sqlList.add(sql);
    }

    public void removeSql(Sql sql) {
        this.sqlList.remove(sql);
    }

    public void reset() throws SQLException {
        // reset default settings
        //Echo.echo("reset default settings");
        if (this.readOnly != this.defaultReadOnly) {
            this.connection.setReadOnly(this.defaultReadOnly);
            this.readOnly = this.defaultReadOnly;
        }

        if (this.transactionIsolation != this.defaultTransactionIsolation) {
            this.connection.setTransactionIsolation(this.defaultTransactionIsolation);
            this.transactionIsolation = this.defaultTransactionIsolation;
        }

        if (this.autoCommit != this.defaultAutoCommit) {
            this.connection.setAutoCommit(this.defaultAutoCommit);
            this.autoCommit = this.defaultAutoCommit;
        }

        for (Sql sql : this.sqlList) {
            sql.close();
        }
        this.sqlList.clear();

        this.connection.clearWarnings();
        //
    }

    public void setDiscard(boolean discard) {
        this.discard = discard;
    }

    public boolean isDiscard() {
        return discard;
    }
    //

}
